home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / os2 / pccts.zip / MAIN.C < prev    next >
C/C++ Source or Header  |  1992-12-08  |  15KB  |  711 lines

  1. /*
  2.  * proto
  3.  *
  4.  * function/variable prototyper.  Can dump just the symbols or
  5.  * symbols and types.  Can also dump out the symbol table for each
  6.  * scope (global, parameter, block-local).  Generates either K&R or
  7.  * ANSI function prototypes.
  8.  *
  9.  * Terence Parr
  10.  * Purdue University
  11.  * July 1991
  12.  * PCCTS Version 1.00
  13.  */
  14. #include <stdio.h>
  15. #include <malloc.h>
  16. #ifdef __STDC__
  17. #include <stdarg.h>
  18. #else
  19. #include <varargs.h>
  20. #endif
  21. #include "stdpccts.h"
  22.  
  23. #define HashTableSize    999
  24. #define StringTableSize    10000
  25.  
  26. AST *root = NULL;
  27. Sym *Globals = NULL;
  28. Sym *Params = NULL;
  29. static int GenANSI = 0;
  30. static int GenVARS = 0;
  31. static int GenFUNCS = 0;
  32. static int JustSymbols = 0;
  33. static int DumpScopes = 0;
  34. int PrintEngl = 0;
  35. static FILE *f = stdin;
  36.  
  37. char *decodeType();
  38.  
  39.  
  40.         /* C m d - L i n e  O p t i o n  S t r u c t  &  F u n c s */
  41.  
  42. typedef struct {
  43.             char *option;
  44.             int  arg;
  45.             void (*process)();
  46.             char *descr;
  47.         } Opt;
  48.  
  49. static void pANSI() { GenANSI = 1; }
  50. static void pVARS() { GenVARS = 1; }
  51. static void pFUNC() { GenFUNCS = 1; }
  52. static void pNAME() { JustSymbols = 1; }
  53. static void pSYM()  { DumpScopes = 1; }
  54. static void pENGL() { PrintEngl = 1; }
  55.  
  56. static void pFILE(s)
  57. char *s;
  58. {
  59.     f = fopen(s, "r");
  60.     if ( f == NULL )
  61.     {
  62.         fprintf(stderr, "file does not exist: %s\n", s);
  63.         help();
  64.         exit(-1);
  65.     }
  66. }
  67.  
  68. Opt options[] = {
  69.     { "-ansi", 0, pANSI,"Generate ANSI argument prototypes"},
  70.     { "-func", 0, pFUNC,"Generate extern defs for visible functions (default)"},
  71.     { "-var", 0,  pVARS,"Generate extern defs for visible variables (default)"},
  72.     { "-name", 0, pNAME,"Generate visible symbols w/o types"},
  73.     { "-sym", 0,  pSYM, "Dump symbols for each scope"},
  74.     { "-engl", 0, pENGL,"Print english translation"},
  75.     { "*",   0,   pFILE,     "" },    /* anything else is a file */
  76.     { NULL, 0,    NULL, NULL }
  77. };
  78.  
  79. main(argc, argv)
  80. int argc;
  81. char **argv;
  82. {
  83.     if ( argc != 1 ) ProcessArgs(argc-1, &(argv[1]), options);
  84.  
  85.     zzs_init(HashTableSize, StringTableSize);
  86.     ANTLR(globals(&root), f);
  87.     zzs_done();
  88.  
  89.     fclose( f ) ;
  90. }
  91.  
  92. pScope(p, s)
  93. Sym *p;
  94. char *s;
  95. {
  96.     if ( p == NULL || !DumpScopes ) return;
  97.     printf("%s", s);
  98.     for (; p!=NULL; p=p->scope)
  99.     {
  100.         printf("Level %02d | %-12s | %-15s",
  101.             p->level,
  102.             zztokens[p->token],
  103.             p->symbol);
  104.         if ( p->token == Var ||
  105.              p->token == Func ||
  106.              p->token == TypeName )
  107.         {
  108.             pType( p->type, NULL );
  109.         }
  110.         printf("\n");
  111.     }
  112. }
  113.  
  114. /*
  115.  * handleSymbol()
  116.  *
  117.  * Description        process the installation of symbols into the symbol
  118.  *                    table.  We handle:
  119.  *                        extern decls followed by the actual
  120.  *                            definitions.  
  121.  *                        typedefs
  122.  *                        function decls/defs (external and definition)
  123.  *                        old-style argument definitions
  124.  *
  125.  * Parameters
  126.  *        sc            storage class of symbol
  127.  *        symbol        symbol to handle
  128.  *        type        type of symbol
  129.  *        init        initialization expression-tree
  130.  *        level        level number (scope)
  131.  *
  132.  * Returns
  133.  *        nothing
  134.  */
  135. handleSymbol(sc, symbol, type, init, level)
  136. int sc;
  137. char *symbol;
  138. AST *type, *init;
  139. int level;
  140. {
  141.     AST *base;
  142.     Sym *n;
  143.  
  144.     /* T y p e d e f
  145.      *
  146.      * typedefs are added immediately in rule declarator and friends
  147.      * so we simply set the level and type here
  148.      */
  149.     if ( sc&scTypedef )
  150.     {
  151.         n = zzs_get(symbol);
  152.         n->level = level;
  153.         n->type = type;
  154.         return;
  155.     }
  156.  
  157.     n = zzs_get(symbol);
  158.  
  159.     /* F u n c t i o n
  160.      *
  161.      * The first extern func declaration is added to the symbol table
  162.      * any subsequent extern decls are ignored.  When an actual definition
  163.      * is seen, we set the 'defined' field in symbol table.
  164.      * If the function has not been seen before, add it to the symbol
  165.      * table.  Set the defined flag if not scExtern.
  166.      */
  167.     if ( type->nodeType == FunctionQ )
  168.     {
  169.         if ( n!=NULL )                            /* then defined already */
  170.         {
  171.             if ( !n->defined )                    /* was extern, now define */
  172.             {
  173.                 if ( !(sc&scExtern) )            /* do we have a def or decl */
  174.                 {
  175.                     n = addsym(Func, symbol, level, type, init);
  176.                     n->defined = 1;
  177.                 }
  178.                 return;
  179.             }
  180.             error1("function redefinition", symbol);
  181.         }
  182.         n = addsym(Func, symbol, level, type, init);
  183.         if ( !(sc&scExtern) )                    /* do we have a def or decl */
  184.         {
  185.             n->defined = 1;
  186.         }
  187.         return;
  188.     }
  189.  
  190.     /* V a r i a b l e
  191.      *
  192.      * If var has been seen before, check for redefinition.  If declared
  193.      * before and this is a definition, set 'defined' flag.  Ignore decls
  194.      * after first one.
  195.      *
  196.      * If level is parameter, we are adding old-style parameters.  The
  197.      * args rule will have added the symbols to the symbol table.
  198.      */
  199.     if ( n != NULL )                /* have we seen it before? */
  200.     {
  201.         if ( level == PARAMETER )    /* set type of parameter */
  202.         {
  203.             if ( n->defined ) error1("redefinition of parameter", symbol);
  204.             n->type = type;
  205.             n->defined = 1;
  206.             return;
  207.         }
  208.         /* if not a variable, we must make new variable entry in sym tab */
  209.         if ( n->token != Var )
  210.         {
  211.             n = addsym(Var, symbol, level, type, init);
  212.             if ( !(sc&scExtern) ) n->defined = 1;
  213.             return;
  214.         }
  215.         if ( !n->defined )            /* was it defined? */
  216.         {
  217.             if ( !(sc&scExtern) )    /* is this a def? */
  218.             {
  219.                 base = bottom(n->type);
  220.                 base->data.t.sc &= ~scExtern;
  221.                 n->defined = 1;
  222.             }
  223.             return;
  224.         }
  225.         if ( sc&scExtern )            /* redefinition? */
  226.             error1("redefinition of variable", symbol);
  227.         return;
  228.     }
  229.     if ( level == PARAMETER )        /* no parameter for this def */
  230.     {
  231.         error1("extraneous parameter declaration ignored", symbol);
  232.         return;
  233.     }
  234.     n = addsym(Var, symbol, level, type, init);
  235.     if ( !(sc&scExtern) ) n->defined = 1;
  236. }
  237.  
  238. /*
  239.  * Given a list of all 'extern' scope variables, dump an 'extern' def
  240.  * for just the variables that are visible outside the file (non-static).
  241.  */
  242. ProtoVars(globals)
  243. Sym *globals;
  244. {
  245.     Sym *p = globals;
  246.     AST *base;
  247.  
  248.     if ( globals == NULL || !GenVARS ) return;
  249.     for (; p!=NULL; p=p->scope)
  250.     {
  251.         if ( p->token == Var )
  252.         {
  253.             base = bottom(p->type);
  254.             if ( base == NULL ) continue;
  255.             if ( base->nodeType!=BaseTypeQ ) continue;
  256.             if ( !(base->data.t.sc&scStatic) &&
  257.                  !(base->data.t.sc&scExtern) )
  258.             {
  259.                 if ( JustSymbols ) printf("%s\n", p->symbol);
  260.                 else
  261.                 {
  262.                     printf("extern");
  263.                     pType(p->type, p->symbol);
  264.                     printf(";\n");
  265.                 }
  266.             }
  267.         }
  268.     }
  269. }
  270.  
  271. Proto(symbol, type)
  272. char *symbol;
  273. AST *type;
  274. {
  275.     if ( type == NULL || !GenFUNCS ) return;
  276.     if ( bottom(type)->data.t.sc&scStatic ) return;
  277.     if ( JustSymbols ) {printf("%s\n", symbol); return;}
  278.     printf("extern");
  279.     pType( zzchild(type), NULL ); /* dump return type ignoring first () */
  280.     printf(" %s(", symbol);
  281.     if ( GenANSI )
  282.     {
  283.         AST *a;
  284.  
  285.         if ( zzsibling(type)!=NULL )
  286.         {
  287.             for (a=zzsibling(type); a!=NULL; a = zzsibling(a))
  288.             {
  289.                 if ( a->nodeType == SymQ )
  290.                 {
  291.                     if ( zzchild(a)!=NULL )
  292.                         pType(zzchild(a), NULL);
  293.                     else
  294.                     {
  295.                         Sym *n = zzs_get(a->data.s.name);
  296.                         printf(" %s", a->data.s.name);
  297.                     }
  298.                 }
  299.                 else pType(a, NULL);    /* assume ,... here */
  300.                 if ( zzsibling(a) != NULL ) printf(",");
  301.             }
  302.         }
  303.         else
  304.             printf(" void");
  305.     }
  306.     printf(" );\n");
  307. }
  308.  
  309. pArgs( args, comma )
  310. Sym *args;
  311. int comma;
  312. {
  313.     if ( args == NULL ) return;
  314.     pArgs( args->scope, 1 );    /* print the next one first, then this one */
  315.     pType( args->type, NULL );
  316.     if ( comma ) printf(",");
  317. }
  318.  
  319. pType(p, symbol)
  320. AST *p;
  321. char *symbol;
  322. {
  323.     char temp[500], out[500], *s;
  324.  
  325.     temp[0] = out[0] = '\0';
  326.     if ( symbol != NULL ) strcpy(out, symbol);
  327.     while ( p!=NULL )
  328.     {
  329.         switch ( p->nodeType )
  330.         {
  331.             case BaseTypeQ :
  332.                 s = decodeType(&p->data.t);
  333.                 if ( out[0] == '\0' ) sprintf(temp, "%s", s);
  334.                 else sprintf(temp, "%s %s", s, out);
  335.                 strcpy(out, temp);
  336.                 break;
  337.             case PointerQ :
  338.                 temp[0] = '\0';
  339.                 if ( p->down->nodeType == ArrayQ ||
  340.                      p->down->nodeType == FunctionQ )
  341.                 {
  342.                     strcpy(temp, "(");
  343.                 }
  344.                 if ( p->data.p.cv&cvConst )
  345.                     strcat(temp, "* constant");
  346.                 else if ( p->data.p.cv&cvVolatile )
  347.                     strcat(temp, "* volatile");
  348.                 else
  349.                     strcat(temp, "*");
  350.                 strcat(temp, out);
  351.                 if ( p->down->nodeType == ArrayQ ||
  352.                      p->down->nodeType == FunctionQ )
  353.                 {
  354.                     strcat(temp, ")");
  355.                 }
  356.                 strcpy(out, temp);
  357.                 break;
  358.             case ArrayQ :
  359.                 strcat(out, "[]");
  360.                 break;
  361.             case FunctionQ :
  362.                 strcat(out, "()");
  363.                 break;
  364.             default :
  365.                 fprintf(stderr, "pType: illegal nodetype\n");
  366.                 exit(-1);
  367.         }
  368.         p = p->down;
  369.     }
  370.     printf("%s", out);
  371. }
  372.  
  373. char *
  374. decodeType(base)
  375. qBaseType *base;
  376. {
  377.     static char temp[255], temp2[255];
  378.  
  379.     temp[0]=temp2[0]='\0';
  380.     if ( base->sc&scAuto )        strcat(temp," auto");
  381.     if ( base->sc&scRegister )    strcat(temp," register");
  382.     if ( base->sc&scStatic )    strcat(temp," static");
  383.     if ( base->sc&scExtern )    strcat(temp," extern");
  384.  
  385.     if ( base->cv&cvConst )        strcat(temp," constant");
  386.     if ( base->cv&cvVolatile )    strcat(temp," volatile");
  387.  
  388.     if ( base->type&tSigned )    strcat(temp," signed");
  389.     if ( base->type&tUnsigned)    strcat(temp," unsigned");
  390.     if ( base->type&tShort )    strcat(temp," short");
  391.     if ( base->type&tLong )        strcat(temp," long");
  392.     if ( base->type&tDouble )    strcat(temp," double");
  393.     if ( base->type&tInt )        strcat(temp," int");
  394.     if ( base->type&tFloat )    strcat(temp," float");
  395.     if ( base->type&tChar )        strcat(temp," char");
  396.     if ( base->type&tVoid )        strcat(temp," void");
  397.     if ( base->type&tEllipsis)    strcat(temp," ...");
  398.     if ( base->type&tUnion )
  399.     {
  400.         sprintf(temp2, " union %s",base->name!=NULL?base->name:"");
  401.         strcat(temp, temp2);
  402.     }
  403.     if ( base->type&tStruct)
  404.     {
  405.         sprintf(temp2, " struct %s",base->name!=NULL?base->name:"");
  406.         strcat(temp, temp2);
  407.     }
  408.     if ( base->type&tEnum )
  409.     {
  410.         sprintf(temp2, " union %s",base->name!=NULL?base->name:"");
  411.         strcat(temp, temp2);
  412.     }
  413.     if ( base->type&tTypeName)
  414.     {
  415.         sprintf(temp2, " %s",base->name);
  416.         strcat(temp, temp2);
  417.     }
  418.     return temp;
  419. }
  420.  
  421. /* Constructor for AST nodes
  422.  * First parameter is always pointer to newly-created AST node
  423.  * Second is the AST node type which will tell us what follows
  424.  * on the stack.
  425.  */
  426.  
  427. #ifdef __STDC__
  428. AST *zzmk_ast(AST *t, int nt, ...)
  429. #else
  430. AST *zzmk_ast(va_alist)
  431. va_dcl
  432. #endif
  433. {
  434. #ifndef __STDC__
  435.     int nt;
  436.     AST *t;
  437. #endif
  438.     va_list ap;
  439.  
  440. #ifdef __STDC__
  441.     va_start(ap, nt);
  442. #else
  443.     va_start(ap);
  444.     t = va_arg(ap, AST *);
  445.     nt = va_arg(ap, int);
  446. #endif
  447.  
  448.     t->nodeType = nt;
  449.     switch ( t->nodeType )
  450.     {
  451.         case BaseTypeQ :
  452.             t->data.t.cv = va_arg(ap, int);
  453.             t->data.t.sc = va_arg(ap, int);
  454.             t->data.t.type = va_arg(ap, int);
  455.             t->data.t.name = strdup( va_arg(ap, char *) );
  456.             break;
  457.         case PointerQ :
  458.             t->data.p.cv = va_arg(ap, int);
  459.             break;
  460.         case ArrayQ :
  461.             t->data.a.dim = va_arg(ap, AST *);
  462.             break;
  463.         case FunctionQ :
  464.             break;
  465.         case FieldQ :
  466.             t->data.fi.name = strdup( va_arg(ap, char *) );
  467.             break;
  468.         case SymQ :
  469.             t->data.s.name = strdup( va_arg(ap, char *) );
  470.             t->data.s.init = va_arg(ap, AST *);
  471.             break;
  472.         case ENode :
  473.             t->data.e.token = va_arg(ap, int);
  474.             break;
  475.         default :
  476.             fprintf(stderr, "zzmk_ast: illegal nodetype\n");
  477.             exit(-1);
  478.     }
  479.  
  480.     va_end(ap);
  481.     return t;
  482. }
  483.  
  484. void
  485. fatal(s)
  486. char *s;
  487. {
  488.     error(s);
  489.     exit(-1);
  490. }
  491.  
  492. void
  493. error(s)
  494. char *s;
  495. {
  496.     fprintf(stderr, "line %d, error: %s\n", zzline, s);
  497. }
  498.  
  499. void
  500. warn(s)
  501. char *s;
  502. {
  503.     fprintf(stderr, "line %d, warning: %s\n", zzline, s);
  504. }
  505.  
  506. void
  507. error1(s, s2)
  508. char *s, *s2;
  509. {
  510.     fprintf(stderr, "line %d, error: %s: %s\n", zzline, s, s2);
  511. }
  512.  
  513. void
  514. warn1(s, s2)
  515. char *s, *s2;
  516. {
  517.     fprintf(stderr, "line %d, warning: %s: %s\n", zzline, s, s2);
  518. }
  519.  
  520. /* scan the declarator tree for the FunctionQ node.  If there
  521.  * are any arguments, add them to the symbol table for parameters
  522.  * using the scope passed in.
  523.  *
  524.  * The arguments are siblings of the FunctionQ node in the type
  525.  * tree.  e.g.
  526.  *
  527.  *        ...
  528.  *         |
  529.  *         v
  530.  *    [FunctionQ]-->[arg1]--> ... -->[argn]
  531.  *         |            |                 |
  532.  *         v            v                 v
  533.  *        ...         [type1]          [type1]
  534.  *
  535.  * Check for inconsistent definitions.
  536.  *
  537.  * Return a pointer to the first argument (NULL if there is none)
  538.  * Also, return NULL if new-style arguments are found since
  539.  * we won't need to check them later.
  540.  */
  541. AST *
  542. defineArgs(a, scope)
  543. AST *a;
  544. Sym **scope;
  545. {
  546.     Sym **save = zzs_scope( NULL );
  547.     AST *b, *args;
  548.     int which = 0;    /* 1 implies old-style, 2 implies new-style defs */
  549.  
  550.     while ( a != NULL )
  551.     {
  552.         if ( a->nodeType == FunctionQ ) break;
  553.         a = zzchild( a );
  554.     }
  555.     if ( a == NULL )        /* no parameters */
  556.     {
  557.         return NULL;
  558.     }
  559.  
  560.     zzs_scope( scope );
  561.     for (a=args=zzsibling(a); a != NULL; a = zzsibling(a))
  562.     {
  563.         if ( a->nodeType != SymQ )
  564.         {
  565.             if ( a->nodeType != BaseTypeQ ||
  566.                  (a->nodeType == BaseTypeQ&&a->data.t.type != tEllipsis) )
  567.                 error("how about a name with that type?");
  568.         }
  569.         else if ( zzchild(a) != NULL )
  570.         {
  571.             for (b=zzchild(a); b!=NULL; b=zzchild(b))
  572.             {
  573.                 if ( b->nodeType == BaseTypeQ )        /* type & symbol */
  574.                 {
  575.                     if ( which == 1 )
  576.                         error("mixed old- and new-style parameter definitions");
  577.                     else {
  578.                         which = 2;    /* new-style definition */
  579.                         addsym(Var,
  580.                                a->data.s.name,
  581.                                PARAMETER,
  582.                                zzchild(a),
  583.                                NULL);
  584.                         args = NULL;
  585.                     }
  586.                     break;
  587.                 }
  588.             }
  589.         }
  590.         else            /* old-style parameter */
  591.         {
  592.             if ( which == 2 )
  593.                 error("mixed old- and new-style parameter definitions");
  594.             which = 1;
  595.             /* add parameter to symbol table.  Type is set later */
  596.             addsym(Var, a->data.s.name, PARAMETER, NULL, NULL);
  597.         }
  598.     }
  599.     zzs_scope( save );
  600.  
  601.     return args;
  602. }
  603.  
  604. /* Given a list of arguments from a function argument list, check to
  605.  * see that they are all in the symbol tables as parameters.
  606.  */
  607. checkArgs(args)
  608. AST *args;
  609. {
  610.     AST *a, *type;
  611.     Sym *p;
  612.  
  613.     for (a=args; a!=NULL; a=zzsibling(a))    /* for each argument */
  614.     {
  615.         if ( a->data.s.name == NULL ) continue;
  616.         p = zzs_get( a->data.s.name );
  617.         if ( p == NULL )
  618.             if ( !p->defined )
  619.             {
  620.                 warn1("you forgot to define parameter", a->data.s.name);
  621.                 type = zzastnew();
  622.                 zzmk_ast(type,BaseTypeQ,0,0,tInt,NULL);
  623.                 addsym(Var, a->data.s.name, PARAMETER, type, NULL);
  624.             }
  625.     }
  626. }
  627.  
  628. Sym *
  629. addsym(tok, symbol, level, type, init)
  630. int tok;
  631. char *symbol;
  632. int level;
  633. AST *type, *init;
  634. {
  635.     Sym *p = zzs_newadd(symbol);
  636.  
  637.     if ( p == NULL ) return NULL;
  638.     p->token = tok;
  639.     p->level = level;
  640.     p->type = type;
  641.     p->init = init;
  642.     return p;
  643. }
  644.  
  645. AST *bottom(t)
  646. AST *t;
  647. {
  648.     if ( t==NULL ) return NULL;
  649.     if ( t->down != NULL ) return bottom(t->down);
  650.     return t;
  651. }
  652.  
  653. char *
  654. strdup(s)
  655. char *s;
  656. {
  657.     char *p;
  658.     if ( s == NULL ) return NULL;
  659.     p = malloc(strlen(s)+1);
  660.     if ( p == NULL ) return NULL;
  661.     strcpy(p, s);
  662.     return p;
  663. }
  664.  
  665. help()
  666. {
  667.     Opt *p = options;
  668.     fprintf(stderr, "proto [options] file.c\n");
  669.     while ( *(p->option) != '*' )
  670.     {
  671.         fprintf(stderr, "\t%s %s\t%s\n",
  672.                         p->option,
  673.                         (p->arg)?"___":"   ",
  674.                         p->descr);
  675.         p++;
  676.     }
  677. }
  678.  
  679. ProcessArgs(argc, argv, options)
  680. int argc;
  681. char **argv;
  682. Opt *options;
  683. {
  684.     Opt *p;
  685.  
  686.     if ( argv==NULL ) return;
  687.     while ( argc-- > 0 )
  688.     {
  689.         p = options;
  690.         while ( p->option != NULL )
  691.         {
  692.             if ( strcmp(p->option, "*") == 0 ||
  693.                  strcmp(p->option, *argv) == 0 )
  694.             {
  695.                 if ( p->arg )
  696.                 {
  697.                     (*p->process)( *argv, *(argv+1) );
  698.                     argv++;
  699.                     argc--;
  700.                 }
  701.                 else
  702.                     (*p->process)( *argv );
  703.                 break;
  704.             }
  705.             p++;
  706.         }
  707.         argv++;
  708.     }
  709. }
  710.  
  711.